import logging

from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import joinedload

from blls.base_bll import BaseBLL
from config import REDIS_DATABASE_KEY
from dtos.result import Result
from enumobjects.general_enum import YesOrNoEnum
from libs.redis_wrapper import RedisWrapper
from models.annotation_models.annotation_model import Annotation
from models.data_models.data_model import Data
from models.label_models.label import Label
from models.project_models.project_model import Project
from utils.common_util import CommonUtil


class AnnotationBLL(BaseBLL):
    def save_all(self, data):
        current_user = self.get_current_user()
        annotations = data['annotations']
        data_info = self.db_session.query(Data).filter(
            Data.data_id == data["data_id"],
            Data.is_delete == YesOrNoEnum.NO.value
        ).first()

        if data_info is None:
            return Result.error_result(message="数据不存在")

        try:
            self.db_session.begin(subtransactions=True)

            # 获取当前所有未删除的标注
            curr_anns = self.db_session.query(Annotation).filter(
                Annotation.data_id == data["data_id"],
                Annotation.is_delete == YesOrNoEnum.NO.value
            ).all()
            curr_ann_ids = set(ann.annotation_id for ann in curr_anns)
            keep_ann_ids = []

            for ann in annotations:
                del ann["label"]  # 移除不需要的字段
                if ann.get('annotation_id') is None or ann['annotation_id'] not in curr_ann_ids:
                    new_ann = Annotation(
                        data_id=data_info.data_id,
                        project_id=data_info.project_id,
                        type=ann['type'],
                        frontend_id=ann['frontend_id'],
                        result=ann['result'],
                        label_id=ann.get('label_id'),
                        create_time=CommonUtil.get_timestamp(),
                        last_update_time=CommonUtil.get_timestamp(),
                        create_user_id=current_user.id
                    )
                    self.db_session.add(new_ann)
                else:
                    keep_ann_ids.append(ann['annotation_id'])
                    ann_dict = {
                        "type": ann['type'],
                        "frontend_id": ann['frontend_id'],
                        "result": ann['result'],
                        "last_update_time": CommonUtil.get_timestamp(),
                        "create_user_id": current_user.id
                    }
                    self.db_session.query(Annotation).filter(
                        Annotation.annotation_id == ann['annotation_id'],
                        Annotation.is_delete == YesOrNoEnum.NO.value
                    ).update(ann_dict)

            # 删除不在请求中的标注
            for curr_ann in curr_anns:
                if curr_ann.annotation_id not in keep_ann_ids:
                    curr_ann.is_delete = YesOrNoEnum.YES.value

            self.db_session.commit()

            # 重新查询最新的标注数据
            curr_anns = self.db_session.query(Annotation).filter(
                Annotation.data_id == data["data_id"],
                Annotation.is_delete == YesOrNoEnum.NO.value
            ).all()

            res_data = []
            for ann in curr_anns:
                label = self.db_session.query(Label).filter(
                    Label.label_id == ann.label_id,
                    Label.is_delete == YesOrNoEnum.NO.value
                ).first()
                label_dict = {
                    "label_id": label.label_id,
                    "project_id": label.project_id,
                    "guid": label.guid,
                    "color": label.color,
                    "name": label.name,
                }
                ann_dict = {
                    "annotation_id": ann.annotation_id,
                    "data_id": ann.data_id,
                    "project_id": ann.project_id,
                    "type": ann.type,
                    "frontend_id": ann.frontend_id,
                    "result": ann.result,
                    "label": label_dict,
                    "label_id": ann.label_id,
                    "create_time": CommonUtil.convert_timestamp_to_dt(ann.create_time),
                    "last_update_time": CommonUtil.convert_timestamp_to_dt(ann.last_update_time),
                }
                RedisWrapper.r.rpush(REDIS_DATABASE_KEY + str(ann.project_id) + str(current_user.username), ann.data_id)
                res_data.append(ann_dict)

            return Result.success_result(data=res_data, message="添加成功")

        except SQLAlchemyError as e:
            self.db_session.rollback()
            logging.error(f"Database error: {e}")
            return Result.error_result(message="数据库操作失败")
        except Exception as e:
            self.db_session.rollback()
            logging.error(f"Unexpected error: {e}")
            return Result.error_result(message="未知错误")

    # def save_all(self, data):
    #     current_user = self.get_current_user()
    #     annotations = data['annotations']
    #     data_info = self.db_session.query(Data).filter(Data.data_id == data["data_id"],
    #                                                    Data.is_delete == YesOrNoEnum.NO.value).first()
    #     if data_info is None:
    #         return Result.error_result(message="数据不存在")
    #     for idx in range(len(annotations)):
    #         del annotations[idx]["label"]
    #         if annotations[idx].get('annotation_id', None) is None:
    #             annotations[idx] = Annotation(**annotations[idx])
    #         else:
    #             annotations[idx] = self.db_session.query(Annotation).filter(
    #                 Annotation.annotation_id == annotations[idx]["annotation_id"],
    #                 Annotation.is_delete == YesOrNoEnum.NO.value).first()
    #     curr_anns = self.db_session.query(Annotation).filter(Annotation.data_id == data["data_id"],
    #                                                          Annotation.is_delete == YesOrNoEnum.NO.value).all()
    #     curr_ann_ids = set([ann.annotation_id for ann in curr_anns])
    #     keep_ann_ids = []
    #     self.db_session.begin(subtransactions=True)
    #     for ann in annotations:
    #         if ann.annotation_id is None or ann.annotation_id not in curr_ann_ids:
    #             ann.annotation_id = None
    #             ann.data_id = data_info.data_id
    #             ann.project_id = data_info.project_id
    #             ann.create_time = CommonUtil.get_timestamp()
    #             ann.last_update_time = CommonUtil.get_timestamp()
    #             ann.create_user_id = current_user.id
    #             self.db_session.add(ann)
    #         else:
    #             keep_ann_ids.append(ann.annotation_id)
    #             ann_dict = {
    #                 "annotation_id": ann.annotation_id,
    #                 "data_id": ann.data_id,
    #                 "project_id": ann.project_id,
    #                 "type": ann.type,
    #                 "frontend_id": ann.frontend_id,
    #                 "result": ann.result,
    #                 "label": ann.label_id,
    #                 "create_time": ann.create_time,
    #                 "last_update_time": CommonUtil.get_timestamp(),
    #                 "create_user_id": current_user.id
    #             }
    #             del ann_dict["create_time"]
    #             del ann_dict["annotation_id"]
    #             del ann_dict["label"]
    #             self.db_session.query(Annotation).filter(Annotation.annotation_id == ann.annotation_id,
    #                                                      Annotation.is_delete == YesOrNoEnum.NO.value).update(ann_dict)
    #
    #     for curr_ann in curr_anns:
    #         if curr_ann.annotation_id not in keep_ann_ids:
    #             curr_ann.is_delete = YesOrNoEnum.YES.value
    #             self.db_session.flush()
    #     curr_anns = self.db_session.query(Annotation).filter(Annotation.data_id == data["data_id"],
    #                                                          Annotation.is_delete == YesOrNoEnum.NO.value).all()
    #     self.db_session.commit()
    #     res_data = []
    #     for ann in curr_anns:
    #         label = self.db_session.query(Label).filter(Label.label_id == ann.label_id,
    #                                                     Label.is_delete == YesOrNoEnum.NO.value).first()
    #         label = {
    #             "label_id": label.label_id,
    #             "project_id": label.project_id,
    #             "guid": label.guid,
    #             "color": label.color,
    #             "name": label.name,
    #         }
    #         ann_dict = {
    #             "annotation_id": ann.annotation_id,
    #             "data_id": ann.data_id,
    #             "project_id": ann.project_id,
    #             "type": ann.type,
    #             "frontend_id": ann.frontend_id,
    #             "result": ann.result,
    #             "label": label,
    #             "label_id": ann.label_id,
    #             "create_time": CommonUtil.convert_timestamp_to_dt(ann.create_time),
    #             "last_update_time": CommonUtil.convert_timestamp_to_dt(ann.last_update_time),
    #         }
    #         RedisWrapper.r.rpush(REDIS_DATABASE_KEY + str(ann.project_id) + str(current_user.username),ann.data_id)
    #         res_data.append(ann_dict)
    #     return Result.success_result(data=res_data, message="添加成功")

    def delete_by_id(self, data):
        annotation = self.db_session.query(Annotation).filter(Annotation.annotation_id == data["annotation_id"],
                                                              Annotation.is_delete == YesOrNoEnum.NO.value).first()
        if annotation is None:
            return Result.error_result(message="annotation not found")
        try:
            self.db_session.begin()
            annotation.is_delete = YesOrNoEnum.YES.value
            self.db_session.commit()
            return Result.success_result()
        except Exception as ex:
            message = "添加错误，原因是:%s" % str(ex)
            logging.info(message)
            self.db_session.rollback()
            return Result.error_result(message=message)

    def get_by_data_id(self, data):
        #查询data是否存在
        data_info = self.db_session.query(Data).filter(Data.data_id == data["data_id"],
                                                       Data.is_delete == YesOrNoEnum.NO.value).first()
        if not data_info:
            return Result.error_result(message="data不存在")
        #根据data_id查询注释和与注释关联的标签
        anns = self.db_session.query(Annotation, Label).join(Label,
                                                             Label.label_id == Annotation.label_id
                                                             ).filter(
                                                            Annotation.data_id == data["data_id"],
                                                            Annotation.is_delete == YesOrNoEnum.NO.value).all()
        data_list = []
        for ann in anns:
            label_info = {
                "label_id": ann[1].label_id,
                "guid": ann[1].guid,
                "color": ann[1].color,
                "name": ann[1].name,
            }
            info = {
                "annotation_id": ann[0].annotation_id,
                "data_id": ann[0].data_id,
                "project_id": ann[0].project_id,
                "type": ann[0].type,
                "frontend_id": ann[0].frontend_id,
                "result": ann[0].result,
                "label": label_info,
                "created": ann[0].create_time,
                "modified": ann[0].last_update_time,
                "label_id": ann[0].label_id
            }
            data_list.append(info)
        res_data = {
            "data": data_list,
        }
        return Result.success_result(data=res_data)

    def classify_annotation(self, data):
        current_user = self.get_current_user()
        data_info = self.db_session.query(Data).filter(Data.data_id == data["data_id"],
                                                       Data.is_delete == YesOrNoEnum.NO.value).first()
        if not data_info:
            return Result.error_result(message="data不存在")
        label = self.db_session.query(Label).filter(Label.label_id == data["label_id"],
                                                    Label.is_delete == YesOrNoEnum.NO.value).first()
        if not label:
            return Result.error_result(message="label不存在")
        project = self.db_session.query(Project).filter(Project.project_id == label.project_id,
                                                        Project.is_delete == YesOrNoEnum.NO.value).first()
        if not project:
            return Result.error_result(message="project不存在")
        try:
            self.db_session.begin(subtransactions=True)
            if data["result"] == "":
                ann_info = self.db_session.query(Annotation).filter(Annotation.data_id == data["data_id"],
                                                                    Annotation.is_delete == YesOrNoEnum.NO.value).first()
                if ann_info is None:
                    ann_info = Annotation(**{
                        "create_time": CommonUtil.get_timestamp(),
                        "last_update_time": CommonUtil.get_timestamp(),
                        "data_id": data["data_id"],
                        "label_id": data["label_id"],
                        "project_id": project.project_id,
                        "create_user_id": current_user.id
                    })
                    RedisWrapper.r.rpush(REDIS_DATABASE_KEY + str(project.project_id) + str(current_user.username),
                                         data["data_id"])
                    self.db_session.add(ann_info)
                else:
                    ann_info.data_id = data["data_id"]
                    ann_info.label_id = data["label_id"]
                    ann_info.project_id = project.project_id
                    ann_info.create_user_id = current_user.id
            else:
                ann_info = {
                    "create_time": CommonUtil.get_timestamp(),
                    "last_update_time": CommonUtil.get_timestamp(),
                    "data_id": data["data_id"],
                    "project_id": project.project_id,
                    "label_id": data["label_id"],
                    "frontend_id": data["frontend_id"],
                    "result": data["result"],
                    "type": data["type"],
                    "create_user_id": current_user.id
                }
                ann_info = Annotation(**ann_info)
                RedisWrapper.r.rpush(REDIS_DATABASE_KEY + str(project.project_id) + str(current_user.username), data["data_id"])
                self.db_session.add(ann_info)
            self.db_session.commit()
        except Exception as ex:
            message = "添加错误，原因是:%s" % str(ex)
            logging.info(message)
            self.db_session.rollback()
            return Result.error_result(message=message)
        label_info = {
            "label_id": label.label_id,
            "project_id": label.project_id,
            "guid": label.guid,
            "color": label.color,
            "name": label.name
        }
        res_data = [{
            "created": CommonUtil.convert_timestamp_to_dt(ann_info.create_time),
            "modified": CommonUtil.convert_timestamp_to_dt(ann_info.last_update_time),
            "data_id": ann_info.data_id,
            "project_id": ann_info.project_id,
            "label_id": ann_info.label_id,
            "label": label_info,
            "type": ann_info.type,
            "frontend_id": ann_info.frontend_id,
            "result": ann_info.result,
            "annotation_id": ann_info.annotation_id
        }]
        return Result.success_result(data=res_data)

    def update_annotation(self, data):
        annotation_info = self.db_session.query(Annotation).filter(Annotation.annotation_id == data["annotation_id"],
                                                                   Annotation.is_delete == 0).first()
        if not annotation_info:
            return Result.error_result(message="annotation不存在")
        try:
            self.db_session.begin(subtransactions=True)
            annotation_info.frontend_id = data["frontend_id"]
            annotation_info.type = data["type"]
            annotation_info.last_update_time = CommonUtil.get_timestamp()
            annotation_info.result = data["result"]
            self.db_session.commit()
        except Exception as ex:
            message = "更新错误，原因是:%s" % str(ex)
            logging.info(message)
            self.db_session.rollback()
            return Result.error_result(message=message)
        ann = self.db_session.query(Annotation).filter(Annotation.annotation_id == data["annotation_id"],
                                                       Annotation.is_delete == 0).first()
        label = self.db_session.query(Label).filter(Label.label_id == ann.label_id,
                                                    Label.is_delete == 0).first()
        label_info = {
            "label_id": label.label_id,
            "project_id": label.project_id,
            "guid": label.guid,
            "color": label.color,
            "name": label.name,
            "super_category_id": label.super_category_id,
        }
        res_data = {
            "annotation_id": ann.annotation_id,
            "created": ann.create_time,
            "modified": ann.last_update_time,
            "data_id": ann.data_id,
            "project_id": ann.project_id,
            "label_id": ann.label_id,
            "label": label_info,
            "type": ann.type,
            "frontend_id": ann.frontend_id,
            # "predicted_by": ann.predicted_by,
            "result": ann.result,
        }
        return Result.success_result(data=res_data)

    def annotation_detail(self, data):
        #根据annotation_id查询注释
        ann = self.db_session.query(Annotation).filter(Annotation.annotation_id == data["annotation_id"],
                                                       Annotation.is_delete == 0).first()
        if ann is None:
            return Result.error_result(message="annotation not found")
        #根据label_id查询label
        label = self.db_session.query(Label).filter(Label.label_id == ann.label_id,
                                                    Label.is_delete == 0).first()
        label_info = {
            "label_id": label.label_id,
            "project_id": label.project_id,
            "guid": label.guid,
            "color": label.color,
            "name": label.name,
            "super_category_id": label.super_category_id,
        }
        info = {
            "annotation_id": ann.annotation_id,
            "created": ann.create_time,
            "modified": ann.last_update_time,
            "data_id": ann.data_id,
            "project_id": ann.project_id,
            "label_id": ann.label_id,
            "label": label_info,
            "type": ann.type,
            "frontend_id": ann.frontend_id,
            # "predicted_by": ann.predicted_by,
            "result": ann.result,
        }
        return Result.success_result(data=info)
